"""
Tag Management Service
标签管理服务 - 标签管理和内容关联
"""

import uuid
from typing import Optional, Dict, Any, List
from datetime import datetime

from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, and_, or_, func, update
from sqlalchemy.orm import selectinload
import structlog

from ..models.user import User
from ..models.content_tag import ContentTag, TagCategory, TagVisibility
from ..models.generated_content import GeneratedContent
from ..core.database import DatabaseSession
from ..core.config import settings
from ..core.exceptions import (
    TagNotFoundError,
    TagAlreadyExistsError,
    ValidationError,
    PermissionDeniedError,
)

# 配置结构化日志
logger = structlog.get_logger(__name__)


class TagManagementService:
    """标签管理服务类"""

    def __init__(self, db_session: DatabaseSession):
        self.db_session = db_session

    async def create_tag(
        self,
        user: User,
        name: str,
        display_name: Optional[str] = None,
        description: Optional[str] = None,
        category: str = TagCategory.CUSTOM,
        color: Optional[str] = None,
        icon: Optional[str] = None,
        visibility: str = TagVisibility.PUBLIC,
        language: str = "zh-CN",
        **kwargs
    ) -> ContentTag:
        """
        创建标签

        Args:
            user: 用户对象
            name: 标签名称
            display_name: 显示名称
            description: 描述
            category: 分类
            color: 颜色
            icon: 图标
            visibility: 可见性
            language: 语言
            **kwargs: 其他参数

        Returns:
            ContentTag: 创建的标签

        Raises:
            ValidationError: 参数验证失败
            TagAlreadyExistsError: 标签已存在
        """
        logger.info("创建标签", user_id=str(user.id), name=name, category=category)

        # 验证参数
        await self._validate_tag_params(name, display_name, description, category, visibility, language)

        # 生成slug
        slug = self._generate_slug(name)

        async with self.db_session as session:
            # 检查名称冲突
            conflict_query = select(ContentTag).where(
                and_(
                    ContentTag.name == name,
                    ContentTag.visibility == visibility,
                    ContentTag.is_system == False
                )
            )
            conflict_result = await session.execute(conflict_query)
            if conflict_result.scalar_one_or_none():
                raise TagAlreadyExistsError(f"标签 '{name}' 已存在")

            # 检查slug冲突
            if slug:
                slug_query = select(ContentTag).where(
                    and_(
                        ContentTag.slug == slug,
                        ContentTag.visibility == visibility
                    )
                )
                slug_result = await session.execute(slug_query)
                if slug_result.scalar_one_or_none():
                    # 如果slug冲突，添加后缀
                    slug = f"{slug}-{uuid.uuid4().hex[:8]}"

            # 创建标签
            tag = ContentTag(
                name=name,
                display_name=display_name or name,
                description=description,
                category=category,
                color=color,
                icon=icon,
                visibility=visibility,
                language=language,
                slug=slug,
                is_system=False,
                is_active=True,
                **kwargs
            )

            session.add(tag)
            await session.commit()
            await session.refresh(tag)

            logger.info("标签创建成功", tag_id=str(tag.id), name=name)
            return tag

    async def get_tag(self, tag_id: uuid.UUID) -> Optional[ContentTag]:
        """
        获取标签

        Args:
            tag_id: 标签ID

        Returns:
            Optional[ContentTag]: 标签对象，不存在返回None
        """
        async with self.db_session as session:
            result = await session.execute(
                select(ContentTag)
                .where(ContentTag.id == tag_id)
                .options(selectinload(ContentTag.parent), selectinload(ContentTag.children))
            )
            return result.scalar_one_or_none()

    async def get_tag_by_name(self, name: str, visibility: Optional[str] = None) -> Optional[ContentTag]:
        """
        根据名称获取标签

        Args:
            name: 标签名称
            visibility: 可见性过滤

        Returns:
            Optional[ContentTag]: 标签对象，不存在返回None
        """
        async with self.db_session as session:
            query = select(ContentTag).where(ContentTag.name == name)
            
            if visibility:
                query = query.where(ContentTag.visibility == visibility)
            
            result = await session.execute(query)
            return result.scalar_one_or_none()

    async def get_tags(
        self,
        user: Optional[User] = None,
        category: Optional[str] = None,
        visibility: Optional[str] = None,
        is_system: Optional[bool] = None,
        is_active: Optional[bool] = None,
        search: Optional[str] = None,
        skip: int = 0,
        limit: int = 100
    ) -> List[ContentTag]:
        """
        获取标签列表

        Args:
            user: 用户对象（用于权限过滤）
            category: 分类过滤
            visibility: 可见性过滤
            is_system: 是否系统标签过滤
            is_active: 是否激活过滤
            search: 搜索关键词
            skip: 跳过数量
            limit: 限制数量

        Returns:
            List[ContentTag]: 标签列表
        """
        async with self.db_session as session:
            query = select(ContentTag)

            # 应用过滤条件
            if category:
                query = query.where(ContentTag.category == category)
            if visibility:
                query = query.where(ContentTag.visibility == visibility)
            if is_system is not None:
                query = query.where(ContentTag.is_system == is_system)
            if is_active is not None:
                query = query.where(ContentTag.is_active == is_active)

            # 权限过滤
            if user:
                # 用户可以看到：公开标签、自己的私有标签、系统标签
                query = query.where(
                    or_(
                        ContentTag.visibility == TagVisibility.PUBLIC,
                        ContentTag.visibility == TagVisibility.SYSTEM,
                        and_(
                            ContentTag.visibility == TagVisibility.PRIVATE,
                            # 这里需要关联用户，但当前模型结构不支持
                            # 暂时只返回公开和系统标签
                        )
                    )
                )
            else:
                # 未登录用户只能看到公开和系统标签
                query = query.where(
                    ContentTag.visibility.in_([TagVisibility.PUBLIC, TagVisibility.SYSTEM])
                )

            # 搜索
            if search:
                search_filter = or_(
                    ContentTag.name.ilike(f"%{search}%"),
                    ContentTag.display_name.ilike(f"%{search}%"),
                    ContentTag.description.ilike(f"%{search}%")
                )
                query = query.where(search_filter)

            # 排序
            query = query.order_by(
                ContentTag.is_system.desc(),  # 系统标签优先
                ContentTag.usage_count.desc(),  # 使用次数多的优先
                ContentTag.name.asc()
            )

            # 分页
            query = query.offset(skip).limit(limit)

            result = await session.execute(query)
            return result.scalars().all()

    async def update_tag(
        self,
        tag_id: uuid.UUID,
        user: User,
        display_name: Optional[str] = None,
        description: Optional[str] = None,
        color: Optional[str] = None,
        icon: Optional[str] = None,
        visibility: Optional[str] = None,
        is_active: Optional[bool] = None,
        **kwargs
    ) -> ContentTag:
        """
        更新标签

        Args:
            tag_id: 标签ID
            user: 用户对象
            display_name: 显示名称
            description: 描述
            color: 颜色
            icon: 图标
            visibility: 可见性
            is_active: 是否激活
            **kwargs: 其他参数

        Returns:
            ContentTag: 更新后的标签

        Raises:
            TagNotFoundError: 标签不存在
            PermissionDeniedError: 无权操作
            ValidationError: 参数验证失败
        """
        logger.info("更新标签", tag_id=str(tag_id), user_id=str(user.id))

        async with self.db_session as session:
            result = await session.execute(
                select(ContentTag).where(ContentTag.id == tag_id)
            )
            tag = result.scalar_one_or_none()

            if not tag:
                raise TagNotFoundError(f"标签 {tag_id} 不存在")

            # 检查权限
            if tag.is_system and not user.is_admin:
                raise PermissionDeniedError("无权更新系统标签")

            # 验证参数
            await self._validate_tag_params(
                None, display_name, description, tag.category, 
                visibility or tag.visibility, tag.language
            )

            # 更新字段
            if display_name is not None:
                tag.display_name = display_name
            if description is not None:
                tag.description = description
            if color is not None:
                tag.color = color
            if icon is not None:
                tag.icon = icon
            if visibility is not None:
                tag.visibility = visibility
            if is_active is not None:
                tag.is_active = is_active

            # 更新其他字段
            for key, value in kwargs.items():
                if hasattr(tag, key):
                    setattr(tag, key, value)

            await session.commit()
            await session.refresh(tag)

            logger.info("标签更新成功", tag_id=str(tag_id))
            return tag

    async def delete_tag(self, tag_id: uuid.UUID, user: User) -> bool:
        """
        删除标签

        Args:
            tag_id: 标签ID
            user: 用户对象

        Returns:
            bool: 是否成功删除

        Raises:
            TagNotFoundError: 标签不存在
            PermissionDeniedError: 无权操作
            ValidationError: 标签无法删除
        """
        logger.info("删除标签", tag_id=str(tag_id), user_id=str(user.id))

        async with self.db_session as session:
            result = await session.execute(
                select(ContentTag).where(ContentTag.id == tag_id)
            )
            tag = result.scalar_one_or_none()

            if not tag:
                raise TagNotFoundError(f"标签 {tag_id} 不存在")

            # 检查权限
            if tag.is_system and not user.is_admin:
                raise PermissionDeniedError("无权删除系统标签")

            # 检查是否有关联的内容
            from ..models.content_tag import content_tag_associations
            association_result = await session.execute(
                select(func.count(content_tag_associations.c.content_id))
                .where(content_tag_associations.c.tag_id == tag_id)
            )
            association_count = association_result.scalar()
            
            if association_count > 0:
                raise ValidationError(f"标签被 {association_count} 个内容使用，无法删除")

            # 删除标签
            await session.delete(tag)
            await session.commit()

            logger.info("标签删除成功", tag_id=str(tag_id))
            return True

    async def add_content_tag(
        self,
        content_id: uuid.UUID,
        tag_id: uuid.UUID,
        user: User,
        confidence: int = 100,
        is_auto_generated: bool = False
    ) -> bool:
        """
        为内容添加标签

        Args:
            content_id: 内容ID
            tag_id: 标签ID
            user: 用户对象
            confidence: 置信度
            is_auto_generated: 是否自动生成

        Returns:
            bool: 是否成功添加

        Raises:
            ValidationError: 参数验证失败
        """
        logger.info("为内容添加标签", content_id=str(content_id), tag_id=str(tag_id), user_id=str(user.id))

        async with self.db_session as session:
            # 获取内容和标签
            content_result = await session.execute(
                select(GeneratedContent).where(GeneratedContent.id == content_id)
            )
            content = content_result.scalar_one_or_none()

            tag_result = await session.execute(
                select(ContentTag).where(ContentTag.id == tag_id)
            )
            tag = tag_result.scalar_one_or_none()

            if not content or not tag:
                raise ValidationError("内容或标签不存在")

            # 检查权限
            if content.user_id != user.id and not user.is_admin:
                raise PermissionDeniedError("无权为此内容添加标签")

            # 检查标签可见性
            if tag.visibility == TagVisibility.PRIVATE and tag.user_id != user.id:
                raise PermissionDeniedError("无权使用此标签")

            # 验证置信度
            if not 0 <= confidence <= 100:
                raise ValidationError("置信度必须在0-100之间")

            # 检查是否已存在关联
            from ..models.content_tag import content_tag_associations
            existing_result = await session.execute(
                select(content_tag_associations.c.content_id)
                .where(
                    and_(
                        content_tag_associations.c.content_id == content_id,
                        content_tag_associations.c.tag_id == tag_id
                    )
                )
            )
            if existing_result.scalar_one_or_none():
                logger.info("标签已存在，无需重复添加", content_id=str(content_id), tag_id=str(tag_id))
                return False

            # 添加关联
            await session.execute(
                content_tag_associations.insert().values(
                    content_id=content_id,
                    tag_id=tag_id,
                    created_at=datetime.utcnow(),
                    confidence=confidence,
                    is_auto_generated=is_auto_generated,
                    user_id=user.id
                )
            )

            # 更新标签使用计数
            tag.increment_usage()

            # 更新内容的标签列表
            content.add_tag(tag.name)

            await session.commit()

            logger.info("为内容添加标签成功", content_id=str(content_id), tag_id=str(tag_id))
            return True

    async def remove_content_tag(
        self,
        content_id: uuid.UUID,
        tag_id: uuid.UUID,
        user: User
    ) -> bool:
        """
        移除内容的标签

        Args:
            content_id: 内容ID
            tag_id: 标签ID
            user: 用户对象

        Returns:
            bool: 是否成功移除

        Raises:
            ValidationError: 参数验证失败
        """
        logger.info("移除内容的标签", content_id=str(content_id), tag_id=str(tag_id), user_id=str(user.id))

        async with self.db_session as session:
            # 获取内容和标签
            content_result = await session.execute(
                select(GeneratedContent).where(GeneratedContent.id == content_id)
            )
            content = content_result.scalar_one_or_none()

            tag_result = await session.execute(
                select(ContentTag).where(ContentTag.id == tag_id)
            )
            tag = tag_result.scalar_one_or_none()

            if not content or not tag:
                raise ValidationError("内容或标签不存在")

            # 检查权限
            if content.user_id != user.id and not user.is_admin:
                raise PermissionDeniedError("无权移除此内容的标签")

            # 删除关联
            from ..models.content_tag import content_tag_associations
            delete_result = await session.execute(
                content_tag_associations.delete().where(
                    and_(
                        content_tag_associations.c.content_id == content_id,
                        content_tag_associations.c.tag_id == tag_id
                    )
                )
            )

            if delete_result.rowcount == 0:
                logger.info("标签不存在，无需移除", content_id=str(content_id), tag_id=str(tag_id))
                return False

            # 更新标签使用计数
            tag.decrement_usage()

            # 更新内容的标签列表
            content.remove_tag(tag.name)

            await session.commit()

            logger.info("移除内容的标签成功", content_id=str(content_id), tag_id=str(tag_id))
            return True

    async def get_content_tags(
        self,
        content_id: uuid.UUID,
        user: User
    ) -> List[ContentTag]:
        """
        获取内容的标签

        Args:
            content_id: 内容ID
            user: 用户对象

        Returns:
            List[ContentTag]: 标签列表

        Raises:
            ValidationError: 内容不存在或无权限
        """
        async with self.db_session as session:
            # 获取内容
            content_result = await session.execute(
                select(GeneratedContent).where(GeneratedContent.id == content_id)
            )
            content = content_result.scalar_one_or_none()

            if not content:
                raise ValidationError("内容不存在")

            # 检查权限
            if content.user_id != user.id and not user.is_admin and not content.is_public:
                raise PermissionDeniedError("无权查看此内容的标签")

            # 获取标签
            result = await session.execute(
                select(ContentTag)
                .join(content_tag_associations)
                .where(content_tag_associations.c.content_id == content_id)
                .order_by(ContentTag.usage_count.desc(), ContentTag.name.asc())
            )
            return result.scalars().all()

    async def get_tags_by_content_ids(
        self,
        content_ids: List[uuid.UUID],
        user: User
    ) -> Dict[uuid.UUID, List[ContentTag]]:
        """
        批量获取内容的标签

        Args:
            content_ids: 内容ID列表
            user: 用户对象

        Returns:
            Dict[uuid.UUID, List[ContentTag]]: 内容ID到标签列表的映射
        """
        if not content_ids:
            return {}

        async with self.db_session as session:
            # 获取用户有权访问的内容ID
            accessible_contents = content_ids
            if not user.is_admin:
                content_result = await session.execute(
                    select(GeneratedContent.id)
                    .where(
                        and_(
                            GeneratedContent.id.in_(content_ids),
                            or_(
                                GeneratedContent.user_id == user.id,
                                GeneratedContent.is_public == True
                            )
                        )
                    )
                )
                accessible_contents = [str(cid) for cid in content_result.scalars().all()]

            if not accessible_contents:
                return {}

            # 获取标签
            from ..models.content_tag import content_tag_associations
            result = await session.execute(
                select(
                    content_tag_associations.c.content_id,
                    ContentTag
                )
                .select_from(
                    content_tag_associations.join(ContentTag)
                )
                .where(content_tag_associations.c.content_id.in_(accessible_contents))
                .order_by(ContentTag.usage_count.desc(), ContentTag.name.asc())
            )

            # 构建映射
            tag_map = {}
            for content_id, tag in result.all():
                if content_id not in tag_map:
                    tag_map[content_id] = []
                tag_map[content_id].append(tag)

            return tag_map

    async def get_popular_tags(
        self,
        user: Optional[User] = None,
        category: Optional[str] = None,
        limit: int = 50
    ) -> List[ContentTag]:
        """
        获取热门标签

        Args:
            user: 用户对象（用于权限过滤）
            category: 分类过滤
            limit: 限制数量

        Returns:
            List[ContentTag]: 热门标签列表
        """
        async with self.db_session as session:
            query = select(ContentTag).where(ContentTag.is_active == True)

            # 分类过滤
            if category:
                query = query.where(ContentTag.category == category)

            # 权限过滤
            if user:
                query = query.where(
                    or_(
                        ContentTag.visibility == TagVisibility.PUBLIC,
                        ContentTag.visibility == TagVisibility.SYSTEM
                    )
                )
            else:
                query = query.where(
                    ContentTag.visibility.in_([TagVisibility.PUBLIC, TagVisibility.SYSTEM])
                )

            # 按使用次数排序
            query = query.order_by(
                ContentTag.usage_count.desc(),
                ContentTag.content_count.desc(),
                ContentTag.name.asc()
            ).limit(limit)

            result = await session.execute(query)
            return result.scalars().all()

    async def get_related_tags(
        self,
        tag_id: uuid.UUID,
        user: User,
        limit: int = 20
    ) -> List[ContentTag]:
        """
        获取相关标签（基于共同使用的内容）

        Args:
            tag_id: 标签ID
            user: 用户对象
            limit: 限制数量

        Returns:
            List[ContentTag]: 相关标签列表

        Raises:
            TagNotFoundError: 标签不存在
        """
        async with self.db_session as session:
            # 获取标签
            tag = await self.get_tag(tag_id)
            if not tag:
                raise TagNotFoundError(f"标签 {tag_id} 不存在")

            # 获取使用相同内容的其他标签
            from ..models.content_tag import content_tag_associations
            
            # 获取当前标签使用的内容ID
            content_ids_result = await session.execute(
                select(content_tag_associations.c.content_id)
                .where(content_tag_associations.c.tag_id == tag_id)
            )
            content_ids = [row[0] for row in content_ids_result.all()]

            if not content_ids:
                return []

            # 获取这些内容的其他标签
            related_tags_result = await session.execute(
                select(ContentTag)
                .join(content_tag_associations)
                .where(
                    and_(
                        content_tag_associations.c.content_id.in_(content_ids),
                        content_tag_associations.c.tag_id != tag_id,
                        ContentTag.is_active == True
                    )
                )
                .group_by(ContentTag.id)
                .order_by(func.count(content_tag_associations.c.content_id).desc())
                .limit(limit)
            )

            return related_tags_result.scalars().all()

    async def create_tag_translation(
        self,
        tag_id: uuid.UUID,
        language: str,
        translated_name: str,
        user: User
    ) -> ContentTag:
        """
        创建标签翻译

        Args:
            tag_id: 标签ID
            language: 语言代码
            translated_name: 翻译名称
            user: 用户对象

        Returns:
            ContentTag: 更新后的标签

        Raises:
            TagNotFoundError: 标签不存在
            PermissionDeniedError: 无权操作
            ValidationError: 翻译名称无效
        """
        logger.info("创建标签翻译", tag_id=str(tag_id), language=language, user_id=str(user.id))

        async with self.db_session as session:
            # 获取标签
            result = await session.execute(
                select(ContentTag).where(ContentTag.id == tag_id)
            )
            tag = result.scalar_one_or_none()

            if not tag:
                raise TagNotFoundError(f"标签 {tag_id} 不存在")

            # 检查权限
            if tag.is_system and not user.is_admin:
                raise PermissionDeniedError("无权更新系统标签")

            # 验证翻译名称
            if not translated_name or len(translated_name.strip()) == 0:
                raise ValidationError("翻译名称不能为空")
            if len(translated_name) > 100:
                raise ValidationError("翻译名称过长，最大100字符")

            # 添加翻译
            tag.add_translation(language, translated_name)

            await session.commit()
            await session.refresh(tag)

            logger.info("标签翻译创建成功", tag_id=str(tag_id), language=language)
            return tag

    async def get_tag_statistics(self, user: Optional[User] = None) -> Dict[str, Any]:
        """
        获取标签统计信息

        Args:
            user: 用户对象（用于权限过滤）

        Returns:
            Dict[str, Any]: 统计信息
        """
        async with self.db_session as session:
            # 基础查询
            query = select(ContentTag)

            # 权限过滤
            if user:
                query = query.where(
                    or_(
                        ContentTag.visibility == TagVisibility.PUBLIC,
                        ContentTag.visibility == TagVisibility.SYSTEM
                    )
                )
            else:
                query = query.where(
                    ContentTag.visibility.in_([TagVisibility.PUBLIC, TagVisibility.SYSTEM])
                )

            # 总体统计
            total_result = await session.execute(
                select(
                    func.count(ContentTag.id),
                    func.count(ContentTag.id).filter(ContentTag.is_system == True),
                    func.count(ContentTag.id).filter(ContentTag.is_active == True),
                    func.count(ContentTag.id).filter(ContentTag.visibility == TagVisibility.PUBLIC),
                    func.sum(ContentTag.usage_count),
                    func.sum(ContentTag.content_count)
                )
            )
            total, system_tags, active_tags, public_tags, total_usage, total_content = total_result.first()

            # 按分类统计
            by_category_result = await session.execute(
                select(
                    ContentTag.category,
                    func.count(ContentTag.id),
                    func.sum(ContentTag.usage_count)
                )
                .group_by(ContentTag.category)
                .order_by(func.count(ContentTag.id).desc())
            )
            by_category = [
                {"category": cat, "count": count, "total_usage": usage}
                for cat, count, usage in by_category_result.all()
            ]

            # 热门标签
            popular_tags_result = await session.execute(
                select(ContentTag)
                .where(ContentTag.is_active == True)
                .order_by(ContentTag.usage_count.desc(), ContentTag.content_count.desc())
                .limit(10)
            )
            popular_tags = popular_tags_result.scalars().all()

            return {
                "total_tags": total or 0,
                "system_tags": system_tags or 0,
                "active_tags": active_tags or 0,
                "public_tags": public_tags or 0,
                "total_usage": total_usage or 0,
                "total_content": total_content or 0,
                "by_category": by_category,
                "popular_tags": [
                    {
                        "id": str(tag.id),
                        "name": tag.name,
                        "display_name": tag.display_name,
                        "category": tag.category,
                        "usage_count": tag.usage_count,
                        "content_count": tag.content_count
                    }
                    for tag in popular_tags
                ]
            }

    async def create_system_tags(self) -> int:
        """
        创建系统预定义标签

        Returns:
            int: 创建的标签数量
        """
        from ..models.content_tag import SYSTEM_TAGS

        created_count = 0
        
        async with self.db_session as session:
            for tag_data in SYSTEM_TAGS:
                # 检查是否已存在
                existing_result = await session.execute(
                    select(ContentTag).where(ContentTag.name == tag_data["name"])
                )
                if existing_result.scalar_one_or_none():
                    continue

                # 创建系统标签
                tag = ContentTag(
                    name=tag_data["name"],
                    display_name=tag_data["display_name"],
                    category=tag_data["category"],
                    color=tag_data["color"],
                    is_system=True,
                    visibility=TagVisibility.PUBLIC,
                    is_active=True
                )

                session.add(tag)
                created_count += 1

            await session.commit()

        logger.info("系统标签创建完成", created_count=created_count)
        return created_count

    # 私有辅助方法

    async def _validate_tag_params(
        self,
        name: Optional[str],
        display_name: Optional[str],
        description: Optional[str],
        category: str,
        visibility: str,
        language: str
    ) -> None:
        """验证标签参数"""
        if name is not None:
            if not name or len(name.strip()) == 0:
                raise ValidationError("标签名称不能为空")
            if len(name) > 50:
                raise ValidationError("标签名称过长，最大50字符")

        if display_name is not None:
            if not display_name or len(display_name.strip()) == 0:
                raise ValidationError("显示名称不能为空")
            if len(display_name) > 100:
                raise ValidationError("显示名称过长，最大100字符")

        if description is not None and len(description) > 500:
            raise ValidationError("标签描述过长，最大500字符")

        if category not in [
            TagCategory.CONTENT_TYPE, TagCategory.STYLE, TagCategory.SUBJECT,
            TagCategory.COLOR, TagCategory.EMOTION, TagCategory.TECHNIQUE,
            TagCategory.SCENE, TagCategory.CUSTOM, TagCategory.AI_GENERATED
        ]:
            raise ValidationError(f"无效的标签分类: {category}")

        if visibility not in [TagVisibility.PUBLIC, TagVisibility.PRIVATE, TagVisibility.SYSTEM]:
            raise ValidationError(f"无效的可见性设置: {visibility}")

        if language and len(language) > 10:
            raise ValidationError("语言代码过长，最大10字符")

    def _generate_slug(self, name: str) -> str:
        """生成URL友好的标识符"""
        import re
        import unicodedata
        
        # 标准化Unicode字符
        slug = unicodedata.normalize('NFKD', name)
        slug = slug.encode('ascii', 'ignore').decode('ascii')
        
        # 替换空格和特殊字符
        slug = re.sub(r'[^\w\s-]', '', slug).strip().lower()
        slug = re.sub(r'[-\s]+', '-', slug)
        
        return slug